(function ($) {
    var Drifter = function () {
        this.isDrawing = false; //是否画框中
        this.isCubeDragging = false; //是否移动框中
        this.isCubeResizing = false; //是否改变大小中
        this.startPoint = [0, 0];
        this.cubeOriPoint = [0, 0];
        this.cubeOriSize = [0, 0];
    };

    Drifter.prototype.changeWidth = function (v1, v2) {
        var sum = v1 + v2;
        if (sum + this.$curCube.width() > this.imgWidth) {
            sum = this.imgWidth - this.$curCube.width();
        } else if (sum < 0) {
            sum = 0;
        }
        return sum;
    };

    Drifter.prototype.changeHeight = function (v1, v2) {
        var sum = v1 + v2;
        if (sum + this.$curCube.height() > this.imgHeight) {
            sum = this.imgHeight - this.$curCube.height();
        } else if (sum < 0) {
            sum = 0;
        }
        return sum;
    };

    //新增框
    Drifter.prototype.addCube = function (coord, id) {
        id = id || this.curId || 0;
        if (id) this.removeCube(id);

        var style = '';
        if (coord) {
            style = 'left:' + coord[0] + "px;" + "top:" + coord[1] + "px;"
                + 'width:' + (coord[2] - coord[0]) + "px;" + "height:" + (coord[3] - coord[1]) + "px;"
        }
        this.$main.append('<div dtype="cube" class="drifter-cube drifter-active" style="' + style + '" data-id="' + id + '">' +
            '<div dtype="upBtn" class="drifter-upBtn"></div>' +
            '<div dtype="downBtn" class="drifter-downBtn"></div>' +
            '<div dtype="upLeftBtn" class="drifter-upLeftBtn"></div>' +
            '<div dtype="upRightBtn" class="drifter-upRightBtn"></div>' +
            '<div dtype="downLeftBtn" class="drifter-downLeftBtn"></div>' +
            '<div dtype="downRightBtn" class="drifter-downRightBtn"></div>' +
            '<div dtype="leftBtn" class="drifter-leftBtn"></div>' +
            '<div dtype="rightBtn" class="drifter-rightBtn"></div>' +
            '</div>');
        return this.$main.children().last();
    };

    Drifter.prototype.getPx = function (val) {
        return Number(val.replace("px", ""));
    };

    Drifter.prototype.getImgNaturalDimensions = function (imgUrl) {
        var that = this;
        var img = new Image();
        img.src = imgUrl;
        img.onload = function () {
            that.imgWidth = img.width;
            that.imgHeight = img.height;
            that.$main.css({
                width: img.width,
                height: img.height
            });
            that.$main.show();
        }
    };

    Drifter.prototype.bindEvent = function () {
        var $main = this.$main;
        var that = this;
        $main.mousedown(function (e) {
            e.preventDefault();
            var targetType = $(e.target).attr("dtype");
            that.startPoint = [e.pageX, e.pageY];

            if (targetType === 'main') {
                that.isDrawing = true;
                that.setCurrentCube(that.addCube());
                that.$curCube.css({left: e.offsetX, top: e.offsetY});
            } else if (targetType === 'cube') {
                that.isCubeDragging = true;
                that.setCurrentCube($(e.target));
                that.cubeOriPoint = [that.getPx(that.$curCube.css("left")), that.getPx(that.$curCube.css("top"))];
            } else if (targetType.match(/^upBtn|downBtn|leftBtn|rightBtn|upLeftBtn|upRightBtn|downLeftBtn|downRightBtn$/)) {
                that.isCubeResizing = true;
                that.setCurrentCube($(e.target).parent());
                that.cubeOriPoint = [that.getPx(that.$curCube.css("left")), that.getPx(that.$curCube.css("top"))];
                that.cubeOriSize = [that.$curCube.width(), that.$curCube.height()];
                that.curDirection = targetType;
            }
        }).mousemove(function (e) {
            e.stopPropagation();
            var deviationX = e.pageX - that.startPoint[0];
            var deviationY = e.pageY - that.startPoint[1];
            if (that.isDrawing) {
                that.$curCube.css({
                    width: deviationX,
                    height: deviationY
                });
            } else if (that.isCubeDragging) {
                that.$curCube.css({
                    left: that.changeWidth(that.cubeOriPoint[0], deviationX),
                    top: that.changeHeight(that.cubeOriPoint[1], deviationY)
                });
            } else if (that.isCubeResizing) {
                switch (that.curDirection) {
                    case 'upBtn' :
                        that.$curCube.css({
                            top: that.cubeOriPoint[1] + deviationY,
                            height: that.cubeOriSize[1] - deviationY
                        });
                        break;
                    case 'downBtn' :
                        that.$curCube.height(that.cubeOriSize[1] + deviationY);
                        break;
                    case 'leftBtn' :
                        that.$curCube.css({
                            left: that.cubeOriPoint[0] + deviationX,
                            width: that.cubeOriSize[0] - deviationX
                        });
                        break;
                    case 'rightBtn' :
                        that.$curCube.width(that.cubeOriSize[0] + deviationX);
                        break;
                    case 'upLeftBtn' :
                        that.$curCube.css({
                            top: that.cubeOriPoint[1] + deviationY,
                            height: that.cubeOriSize[1] - deviationY,
                            left: that.cubeOriPoint[0] + deviationX,
                            width: that.cubeOriSize[0] - deviationX
                        });
                        break;
                    case 'upRightBtn' :
                        that.$curCube.css({
                            top: that.cubeOriPoint[1] + deviationY,
                            height: that.cubeOriSize[1] - deviationY,
                            width: that.cubeOriSize[0] + deviationX
                        });
                        break;
                    case 'downLeftBtn' :
                        that.$curCube.css({
                            height: that.cubeOriSize[1] + deviationY,
                            left: that.cubeOriPoint[0] + deviationX,
                            width: that.cubeOriSize[0] - deviationX
                        });
                        break;
                    case 'downRightBtn' :
                        that.$curCube.css({
                            height: that.cubeOriSize[1] + deviationY,
                            width: that.cubeOriSize[0] + deviationX
                        });
                        break;
                }
            }
        });

        $("body").mouseup(function () {
            if (that.isDrawing || that.isCubeDragging || that.isCubeResizing) {
                that.isDrawing = false;
                that.isCubeDragging = false;
                that.isCubeResizing = false;
                if (that.settings.driftEnd) that.settings.driftEnd(that.getCurrentCoord());
            }
        });
    };

    Drifter.prototype.setCurrentCube = function ($cube) {
        this.$curCube = $cube;
        this.$main.find(".drifter-cube").removeClass("drifter-active");
        $cube.addClass("drifter-active");
        if (this.settings.onChangeCube) this.settings.onChangeCube($cube.data("id"));
    };

    Drifter.prototype.setCurrentCubeById = function (id) {
        this.curId = id;
        var $cube = this.$main.find('.drifter-cube[data-id='+id+']');
        this.$curCube = $cube;
        this.$main.find(".drifter-cube").removeClass("drifter-active");
        $cube.addClass("drifter-active");
    };

    Drifter.prototype.getCurrentCoord = function () {
        return this.getCoord(this.$curCube);
    };

    Drifter.prototype.getCoords = function () {
        var that = this;
        var arr = [];
        this.$main.find(".drifter-cube").each(function () {
            arr.push(that.getCoord($(this)));
        });
        return arr;
    };

    Drifter.prototype.getCoord = function ($cube) {
        var left = this.getPx($cube.css("left"));
        var top = this.getPx($cube.css("top"));
        return {
            x1: left,
            y1: top,
            w: $cube.width(),
            h: $cube.height(),
            x2: left + $cube.width(),
            y2: top + $cube.height(),
            id: $cube.data('id')
        };
    };

    Drifter.prototype.removeCube = function (id) {
        this.$main.find('.drifter-cube[data-id='+id+']').remove();
    };

    Drifter.prototype.setCurId = function (id) {
        this.curId = id;
    };

    Drifter.prototype.init = function ($main, settings) {
        var imgUrl = settings.imgUrl;
        this.$main = $main;
        var that = this;
        $main.hide();
        $main.attr("dtype", "main");
        $main.addClass("drifter-main");
        $main.css('background', 'url("' + imgUrl + '") no-repeat');
        this.getImgNaturalDimensions(imgUrl);
        this.bindEvent();

        //框选结束事件
        this.settings = settings;

        //初始化框选
        if (settings.coords) {
            $.each(settings.coords, function (k, coord) {
                that.addCube(coord);
            });
        }
    };

    $.fn.drifter = function (settings) {
        var drifter = new Drifter();
        drifter.init($(this), settings);
        return drifter;
    };
})(jQuery);



